/*
 * AFrame (原 m_data) 的 说明层 (原 m_text) 管理模块
 * @author Zdream
 * @since 0.2.0
 */

/*
 * 原说明层的部分
 */
m_data.i = {

	/**
	 * 存放文本、图片, 以及其它元素对象.
	 * 存放结构 string (number) - Object
	 * 
	 * 其中, 键为 id, 由 illustrate 单独分配;
	 * 
	 * 对应的值, 即每个 Object 元素由以下多个数据组成
	 * {
	 *   elem: Object
	 *     JQuery - DOM 元素, 即控制的 DOM 元素
	 *   option: Object
	 *     选项
	 *   show: boolean
	 *     是否显示
	 *   type: String (默认 "text", 如果是图片则 "image")
	 *     类型
	 *   state: Object
	 *   {
	 *     require: boolean
	 *       图片类型专有, 如果为 true, 说明正在请求图片的 path
	 *   }
	 * }
	 */
	maps: {
	},

	/**
	 * 用于分配 id 的变量.
	 * 它实际是一个计数器, 换句话说分配的 id 是自增的
	 */
	count: 0,
	
	// 字幕、标题、LOG
	/**
	 * 当前为字幕的元素 id.
	 * 如果没有字幕, 为 -1
	 */
	captionId: -1,
	
	/**
	 * 当前为标题的元素 id.
	 * 如果没有字幕, 为 -1
	 */
	titleId: -1,
	
	// 图片
	
	/**
	 * 正在等待缓存的图片的 id 集合.
	 * key : 需求的图片名称 asset.name
	 * value : array, 由所有图片 id 组成
	 */
	requireImagePathIds: {},

	/**
	 * 创建 Text 实例
	 * {
	 *   position: ...,
	 *   anchor: ...,
	 *   rotate: ..., // 现在不做要求
	 *   scale: ..., // 现在不做要求
	 *   opacity: ..., // 现在不做要求
	 *   zindex: ..., // 显示的层级 / 堆叠顺序, z-index
	 *   text: {
	 * 	   color: ..., // 颜色数据 string
	 * 	   fontSize: ..., // 字号 number
	 * 	   font: ..., // 字体 string
	 * 	   align: ..., // 字体 string
	 * 	   text: ... // 文本 string (不允许 Array)
	 *   }
	 * }
	 */
	Text : function(param) {
		this.position = [0, 0];
		this.anchor = [0, 0];
		this.text = {
			color : "black",
			fontSize : "20px",
			font : "fangzheng",
			text : "",
			align : null,
		};
		
		if (param != null) {
			if (param.position != null) {
				this.position = param.position;
			}
			if (param.anchor != null) {
				this.anchor = param.anchor;
			}
			if (param.zindex != null) {
				this.zindex = param.zindex;
			}
			if (param.text != null) {
				var pt = param.text;
				if (pt.color != null) {
					this.text.color = pt.color;
				}
				if (pt.fontSize != null) {
					this.text.fontSize = pt.fontSize;
				}
				if (pt.font != null) {
					this.text.font = pt.font;
				}
				if (pt.text != null) {
					this.text.text = pt.text;
				}
				if (pt.align != null) {
					this.text.align = pt.align;
				}
			}
		}
	},

	/**
	 * 创建 Image 实例
	 * {
	 *   position: ...,
	 *   anchor: ...,
	 *   rotate: ..., // 现在不做要求
	 *   scale: ..., // 现在不做要求
	 *   opacity: ..., // 现在不做要求
	 *   zindex: ..., // 显示的层级, z-index
	 *   
	 *   // 图片
	 *   image: {
	 *     src: ... // 路径, string
	 *     width: ... // max-width, 图像不变形 number
	 *     height: ... // max-height, 图像不变形 number
	 *   }
	 * }
	 */
	Image: function(param) {
		this.position = [0, 0];
		this.anchor = [0, 0];
		
		if (param != null) {
			if (param.position != null) {
				this.position = param.position;
			}
			if (param.anchor != null) {
				this.anchor = param.anchor;
			}
			if (param.zindex != null) {
				this.zindex = param.zindex;
			}
			// TODO
			
			this.image = {};
			if (param.image != null) {
				if (param.image.src != null) {
					this.image.src = param.image.src;
				}
				if (param.image.width != null) {
					this.image.width = param.image.width;
				}
				if (param.image.height != null) {
					this.image.height = param.image.height;
				}
			}
		}
		// TODO
	},

	/**
	 * 产生一个文本元素, 并返回一个 id 句柄.
	 * 用这个 id 能够控制相应的 DOM 元素
	 * 
	 * @param param
	 *   Object 参数数值.
	 *   允许 null. 默认 null.
	 * @return
	 *   number ID (句柄), 用于表示是这个元素.
	 */
	createText : function(param) {
		var textobj = new this.Text(param);
		var v = {
			type : "text",
			state : {}
		};

		v.id = this.count++;
		this.maps[v.id] = v;

		v.option = textobj;
		v.elem = $("<div id=" + v.id + ">" + v.option.text.text + "</div>");
		v.elem.css({position : "absolute"});
		v.elem.css({width : "100%"}); // 暂时

		v.show = false;
		v.elem.hide();
		$("#text").append(v.elem);

		this.set(v.id, textobj);
		return v.id;
	},
	
	/**
	 * 产生一个图片元素, 并返回一个 id 句柄.
	 * 用这个 id 能够控制相应的 DOM 元素
	 * 
	 * @param param
	 *   Object 参数数值.
	 *   允许 null. 默认 null.
	 * @return
	 *   number ID (句柄), 用于表示是这个元素.
	 */
	createImage : function(param){
		var imageobj = new this.Image(param);
		var v = {
			type : "image",
			state : {}
		};
		
		v.id = this.count++;
		this.maps[v.id] = v;
		
		// 从 asset 找 path
		var path = m_data.a.image.datas[imageobj.image.src];

		v.option = imageobj;
		if (path != null) {
			v.elem = $("<img id='" + v.id + "' src='" + imageobj.image.src + "' />");
		} else {
			v.elem = $("<img id='" + v.id + "' />");
			if (imageobj.image.src != null) {
				this.putRequireImagePathId(v.id, imageobj.image.src);
				v.state.require = true;
			}
		}
		v.elem.on("load", function () {
            m_data.i.handleImagePosition(v.id);
        });
		v.elem.css({position : "absolute"});
//		v.elem.css({height : "100%"},{width : "100%"});

		$("#text").append(v.elem);
		
		v.show = false;

		this.set(v.id, imageobj);
		return v.id;
	},

	/**
	 * 将 id 对应的文本进行变化. 后面 set 也可以设置图片等
	 * 
	 * @param id
	 *   number 句柄.
	 *   上面的 createText() 返回的数据
	 * @param param
	 *   Object 参数parqam数值. 允许 null.
	 *   为 null 的话就是什么都不改变.
	 */
	set : function(id, param){
		var option = this.maps[id].option;

		for (var p in param){
			switch (p)
			{
				case "position":
					this.move(id,param.position);
					break;
				case "anchor":
					this.moveTo(id,param.position,param.anchor);
					break;
				case "zindex":
					this.zIndex(id,param.zindex);
					break;
				case "text": {
					var tx = this.maps[id].option.text;
					var tp = param[p];

					for (var p2 in tp){
						switch (p2) {
						case "color":
							this.textColor(id,tp.color);
							break;
						case "text":
							this.setText(id, tp.text);
							break;
						case "align":
							this.textAlign(id,tp.align);
							break;
						case "font":
							this.textFont(id,tp.font);
							break;
						case "fontSize":
							this.textFontSize(id,tp.fontSize);
							break;
						}
					}
				} break;
				case "image": {
					var tx = this.maps[id].option.text;
					var tp = param[p];

					for (var p2 in tp){
						switch (p2) {
						case "width":
							this.setWidth(id, tp.width);
							break;
						case "height":
							this.setHeight(id, tp.height);
							break;
						}
					}
				} break;
			}
		}
	},

	/**
	 * 设置文本
	 */
	setText : function(id, text) {
		var v = this.maps[id];
		v.option.text.text = text;

		v.elem.text(text);
	},

	/**
	 * 显示文本
	 */
	elementShow : function(id) {
		this.maps[id].elem.show();
	},

	/**
	 * 删除该 id 对应的元素, 可以是文本或图片.
	 */
	remove : function(id) {
		this.maps[id].elem.remove();
		
		// 将该 id 从 requireImagePathIds 中删除
		if (this.maps[id].state.require) {
			var src = this.maps[id].option.image.src;
			var array = this.requireImagePathIds[src];
			if (array != null) {
				for (var i = array.length - 1; i >= 0; i--) {
					if (array[i] == id) {
						array.splice(i, 1);
					}
				}
			}
		}
		
		delete this.maps[id];
	},
	
	/**
	 * 隐藏文本
	 */
	elementHide : function(id) {
		this.maps[id].elem.hide();
	},

	/**
	 * 移动距离原来位置 position 距离的新位置
	 * @param position
	 *   这里必须是 2 元数值数组
	 */
	move : function(id, position) {
		var v = this.maps[id];
		var p = [
			v.elem.offset().left + position[0],
			v.elem.offset().top + position[1],
		];
		m_data.i.moveTo(id, p, null);
	},

	/**
	 * 移动到指定位置
	 */
	moveTo : function(id, position, anchor) {
		if (anchor == null) {
			var v = this.maps[id];
			v.option.position=position;

			if ((typeof position) == 'string') {
				v.elem.css({'position':position});
				// TODO
			} else {
				v.elem.css({'margin-left' : position[0], 'margin-top' : position[1]});
			}

		} else {

		}
	},

	/**
	 * 设置文本颜色
	 */
	textColor : function(id, color){
		this.maps[id].elem.css("color", color);
	},

	/**
	 * 设置文本字体大小
	 */
	textFontSize : function(id, fontSize){
		this.maps[id].elem.css("font-size", fontSize);
	},

	/**
	 * 设置文本字体
	 */
	textFont : function(id, font){
		this.maps[id].elem.css("font-family", font);
	},

	/**
	 * 设置文本对齐方式
	 */
	textAlign : function(id, align){
		this.maps[id].elem.css("text-align", align);
	},

	/**
	 * 设置文本或图像的堆叠顺序
	 */
	zIndex : function(id, z){
		this.maps[id].elem.css("z-index", z);
	},

	/**
	 * 设置图像宽度 (暂时)
	 */
	setWidth : function(id, width){
		var v = this.maps[id];
		v.option.image.width = width;
		this.handleImagePosition(id);
	},

	/**
	 * 设置图像长度 (暂时)
	 */
	setHeight : function(id, height){
		var v = this.maps[id];
		v.option.image.height = height;
		this.handleImagePosition(id);
	},

	/**
	 * 强制显示字幕
	 * @param text
	 *   string 字幕文本.
	 */
	putCaption : function(text) {
		var id = this.createText({
			position: [0, 0.8*_height],
			zindex: 1000,
			text: {
				text: text,
				align: "center",
				fontSize: 28
			}
		});
		
		if (this.captionId != -1) {
			this.removeCaption();
		}
		
		this.captionId = id;
		this.elementShow(id);
	},

	/**
	 * 手动清除字幕
	 */
	removeCaption:function(){
		if (this.captionId != -1) {
			this.remove(this.captionId);
		}
		this.captionId = -1;
	},
	
	/**
	 * 强制显示标题
	 * @param text
	 *   string 标题文本.
	 */
	putTitle : function(text){
		var id = this.createText({
			position: [0, 0.4*_height],
			zindex: 1000,
			text: {
				text: text,
				align: "center",
				fontSize: 48
			}
		});
		
		if (this.titleId != -1) {
			this.removeTitle();
		}
		
		this.titleId = id;
		this.elementShow(id);
	},
	
	/**
	 * 强制清除标题
	 */
	removeTitle : function(){
		if (this.titleId != -1) {
			this.remove(this.titleId);
		}
		this.titleId = -1;
	},
	
	// 私有方法
	
	/**
	 * 将图片 id 添加进 requireImagePathIds
	 * @param id
	 *   图片元素 id
	 * @param name
	 *   asset.name
	 */
	putRequireImagePathId : function(id, name) {
		var array;
		if (this.requireImagePathIds[name] == null) {
			array = [id];
			this.requireImagePathIds[name] = array;
			// 请求
			m_data.a.image.requireImage(name);
		} else {
			array = this.requireImagePathIds[name];
			array.push(id);
		}
	},
	
	handleImagePosition : function(id) {
		var v = this.maps[id];
		var w = v.elem.width();
		var h = v.elem.height();
		
		if (h == 0 || w == 0) {
			v.elem.css("margin-left", 0);
			v.elem.css("margin-top", 0);
			return;
		}
		
		var maxw = v.option.image.width;
		var maxh = v.option.image.height;
		if (maxw == 0 || maxh == 0) {
			var option = v.option;
			var left = option.position[0] - w * option.anchor[0];
			var top = option.position[1] - h * option.anchor[1];
			v.elem.css("margin-left", left);
			v.elem.css("margin-top", top);
		} else {
			// w, h 是现在的大小
			// maxw, maxh 是要设置的最大的大小
			
			var pw = maxw / w;
			var ph = maxh / h;
			
			if (pw >= ph) { // 高撑到最大
				h = maxh;
				w = w * ph;
			} else { // 宽撑到最大
				w = maxw;
				h = h * pw;
			}
			
			var option = v.option;
			var left = option.position[0] - w * option.anchor[0];
			var top = option.position[1] - h * option.anchor[1];
			v.elem.css("margin-left", left);
			v.elem.css("margin-top", top);
			v.elem.css("width", w);
			v.elem.css("height", h);
		}
	},

	/**
	 * 注册字幕相关的事件 (订阅)
	 */
	registerCaptionEvent: function(){
		// 模块开始前, 显示字幕
		subscribeEvent("next-module", function(event,argv) {
			var config = currentModule().config;
			if (config == null || config._text == null) {
				return;
			} else {
				if (argv == null || argv.index != 0) {
					m_data.i.putCaption(config._text);
				} else {
					m_data.i.putTitle(config._text);
				}
			}
		});
		// 模块结束时, 删除字幕
		subscribeEvent("module-complete", function(event,argv) {
			// 判断该模块是否有字幕
			if (argv == null || argv.index != 0) {
				m_data.i.removeCaption();
			} else {
				m_data.i.removeTitle();
			}
		});
	},
	
	/**
	 * 注册从资源模块获取图片位置的事件
	 */
	registerImagePathEvent : function() {
		var thiz = this;
		subscribeEvent("access-image-path", function(event, argv) {
			/*
			 * argv:
			 * {name: ..., path: ...}
			 */
			var array = thiz.requireImagePathIds[argv.name];
			if (array != null) {
				var length = array.length;
				for (var i = 0; i < length; i++) {
					var id = array[i];
					var v = thiz.maps[id];
					
					v.elem.attr("src", m_data.a.createImagePath(argv.path));
					v.option.image.src = argv.path;
					v.state.require = false;
				}
			}
		});
	}
}

m_data.i.registerCaptionEvent();
m_data.i.registerImagePathEvent();
